Visualforce Page / ComponentをReactで作る
SalesforceのVisualforce Componentの作成をReactを使って行ってみました。 Vue.jsやAngularなども同様の方法で使えると思います。
Salesforceの環境にDeveloper Edition組織を使っています。
Visualforce Page / Componentの骨組みを作る
VSCodeのコマンドパレットで[SFDX: Create Visualforce Page]を実行してVisualforce Pageの骨組みを作ります。 ここではページ名を[ReactSampleVFPage]にしました。
force-app/main/default/pages/ReactSampleVFPage.page*
が作成されました。
続いて、コマンドパレットで[SFDX: Create Visualforce Component]を実行してVisualforce Componentの骨組みを作ります。 ここではコンポーネント名を[ReactSampleVFComponent]にしました。
force-app/main/default/components/ReactSampleVFComponent.component*
が作成されました。
Hello, Worldを作ってデプロイする
force-app/main/default/pages/ReactSampleVFPage.page
を選択して、下記に変更します。
<apex:page> <!-- Begin Default Content REMOVE THIS --> <h1>Congratulations</h1> <c:ReactSampleVFComponent /> <!-- End Default Content REMOVE THIS --> </apex:page>
続いて、force-app/main/default/components/ReactSampleVFComponent.component
を選択して、下記に変更します。
<apex:component> <!-- Begin Default Content REMOVE THIS --> <h1>Congratulations</h1> Hello, World. <!-- End Default Content REMOVE THIS --> </apex:component>
変更したら、force-app/main/default/
を選択した状態で[SFDX: Deploy Source to Org]を実行して、ReactSampleVFPageとReactSampleVFComponentを組織にデプロイします。
デプロイできたら組織にログインし、[設定] > [Visualforceページ] > [ReactSampleVFPage]に移動して、[Lightning Experience、Lightning コミュニティ、およびモバイルアプリケーションで利用可能]にチェックを入れます。
続いて任意のアプリケーション(ここでは[サービス]を選択)のホームに移動し、画面右上の歯車アイコンをクリックして[編集ページ]をクリックします。
左メニューのVisualforceをドラッグアンドドロップでページ内の任意の箇所に配置し、画面右の[Visualforceページ名]に[ReactSampleVFPage]を指定して保存します。
ホーム画面に「Hello, World」と表示されるようになることを確認します。
ReactでVisualforce Componentを作る
webpackで1ファイルにまとめたbundle.jsを作成し、index.htmlにてこのbundle.jsを読み込んでReactが動作するようにします。 手順は大筋で参考にさせていただいた「Babelとwebpackを使ってES6でReactを動かすまでのチュートリアル」の記事の通りですので、この記事では簡単に手順を示すに留めます。
下準備
$ mkdir react-sample $ cd react-sample $ git init $ npm init -y $ mkdir src dist
ここではプロジェクトディレクトリを[react-sample]としています。
babelとwebpackの設定
$ npm i -D @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/register $ cat > .babelrc { "presets": [ "@babel/preset-env", "@babel/preset-react" ] } $ npm i -D webpack webpack-cli $ npm i -D webpack-dev-server html-webpack-plugin $ cat > webpack.config.js require('@babel/register'); module.exports = require('./development'); $ cat > development.js import path from 'path' import HtmlWebpackPlugin from 'html-webpack-plugin' const src = path.resolve(__dirname, 'src') const dist = path.resolve(__dirname, 'dist') export default { mode: 'development', entry: src + '/index.jsx', output: { path: dist, filename: 'bundle.js' }, module: { rules: [ { test: /\.jsx$/, exclude: /node_modules/, loader: 'babel-loader' } ] }, resolve: { extensions: ['.js', '.jsx'] }, plugins: [ new HtmlWebpackPlugin({ template: src + '/index.html', filename: 'index.html' }) ] }
Reactパッケージのインストール
$ npm i -S react react-dom $ cat > src/index.jsx import React from 'react'; import {render} from 'react-dom'; class App extends React.Component { render () { return <p> Hello React!</p>; } } render(<App/>, document.getElementById('root')); $cat > src/index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>React Test</title> </head> <body> <div id="root"/> </body> </html>
動作確認
./node_modules/.bin/webpack-dev-server
上記コマンドでWebサーバを立ち上げ、http://localhost:8080/にアクセスします。 画面に「Hello, React!」と表示されることを確認します。
Visualforce ComponentにReactアプリケーションを組み込む
webpackを実行してbundle.js
とindex.html
を作成します。
$ ./node_modules/webpack/bin/webpack.js $ ls dist bundle.js index.html
Salesforceの静的リソースに登録するために、zipに固めます。
$ cd dist $ zip ReactSample.zip bundle.js index.html
作成したzipファイルを静的リソースに設定します。
静的リソース名は[ReactSample]としました。
次にforce-app/main/default/pages/ReactSampleVFPage.page
を下記に変更します。
<apex:page showHeader="false" standardStylesheets="false" title="ReactSample" id="page"> <meta charset="utf-8"/> <title>ReactSample Page</title> <c:ReactSampleVFComponent /> <script src="{!URLFOR($Resource.ReactSample, 'bundle.js')}"></script> </apex:page>
先に作成した静的リソースのbundle.jsを{!URLFOR($Resource.ReactSample, 'bundle.js')}
で参照しています。
<script>タグはコンポーネントの呼び出し(<c:ReactSampleVFComponent />
)より後にする必要がありますので注意してください。
続いてforce-app/main/default/components/ReactSampleVFComponent.component
を下記に変更します。
<apex:component> <!-- Begin Default Content REMOVE THIS --> <div id="root"></div> <!-- End Default Content REMOVE THIS --> </apex:component>
id="root"
のdivタグに対してReactが稼働します。
変更したページとコンポーネントを組織にデプロイしたら、組織にログインして任意のアプリケーション(ここでは[サービス]を選択)のホームに移動します。 「ReactSampleVFPage」の箇所に「Hello, React!」と表示されていれば成功です。
ちょっとだけ複雑なReactを動かしてみる
Hello, Worldだけではつまらないので、ちょっとだけ複雑なReactも動かしてみます。
src/index.jsx
を次に変更します。
import React from 'react'; import {render} from 'react-dom'; import Clock from './Clock'; class App extends React.Component { constructor(props) { super(props) this.state = { name: 'somebody' } } onChange(e) { this.setState( {name: e.target.value} ) } render() { return ( <div> <p>お名前: <input type="text" onChange = { this.onChange.bind(this) } /></p> <p>{ this.state.name }さん、こんにちは!</p> <Clock /> </div> ) } } render(<App/>, document.getElementById('root'));
また、src/Clock.jsx
を下記の内容で作成します。
import React from 'react'; import {render} from 'react-dom'; class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div> 現在時刻は{this.state.date.toLocaleTimeString()}です。 </div> ); } } export default Clock;
名前の入力を受け付けて、入力された名前に対して挨拶しつつ現在時刻を伝えるReactアプリケーションです。
再度、webpackを実行し、成果物をzipに固めます。
$ ./node_modules/webpack/bin/webpack.js $ ls dist bundle.js index.html $ cd dist $ zip ReactSample.zip bundle.js index.html
静的リソースReactSampleを新しく作成したReactSample.zipで置き換えて、再度アプリケーション(ここでは[サービス]を選択)のホームに移動します。 作成したReactアプリケーションがSalesforce上で動作していることが確認できます。
まとめ
Visualforce PageとComponentを使って、 ReactアプリケーションをSalesforce上で動作させる方法についてみてきました。 開発したReactアプリケーションをwebpackでまとめれば、あとはそれをSalesforce上で静的リソースとして設定することでVisualforceにて動作させることが可能です。Lightning Web Componentだけでなく、Reactなどの3rd partyの仕組みを使ってもSalesforceの機能を作ることができます。
選択肢の一つとして道具箱に入れてみてください。